import 'package:dbio_utils/base/beans.dart';

import 'chunk.dart';
import 'virtual_offset.dart';

typedef String RenameRefSeq(String s);

String defRenameRefSeq(String s) => s;

num longToNumber(double long) {
  return long;
}

class IndexBean extends MapBean {
  IndexBean([Map map]) : super(map);

  int get metaChar => this['metaChar'];
  int get skipLines => this['skipLines'];
  get indices => this['indices'];
  Map get columnNumbers => this['columnNumbers'];
  String get coordinateType => this['coordinateType'];
  String get format => this['coordinateType'];
  int get maxBlockSize => this['maxBlockSize'];
  get refIdToName => this['refIdToName'];
  get refNameToId => this['refNameToId'];
  VirtualOffset get firstDataLine => this['firstDataLine'];
  VirtualOffset get maxBinNumber => this['maxBinNumber'];
  int get maxRefLength => this['maxRefLength'];
}

class CsiBean extends IndexBean {
  CsiBean([Map map]) : super(map);

  bool get csi => true;
  int get refCount => this['refCount'];
  int get csiVersion => this['csiVersion'];
  int get depth => this['depth'];
}

class TbiBean extends IndexBean {
  TbiBean([Map map]) : super(map);
}

class BaiBean extends IndexBean {
  BaiBean([Map map]) : super(map);
}

class AbortError extends Error {
  String code;
  AbortError(this.code);
}

class AbortSignal {
  bool aborted;
  AbortSignal(this.aborted);
}

/// Properly check if the given AbortSignal is aborted.
/// Per the standard, if the signal reads as aborted,
/// this function throws either a DOMException AbortError, or a regular error
/// with a `code` attribute set to `ERR_ABORTED`.
///
/// For convenience, passing `undefined` is a no-op
///
/// @param {AbortSignal} [signal] an AbortSignal, or anything with an `aborted` attribute
/// @returns nothing
void checkAbortSignal(AbortSignal signal) {
  if (signal == null) return;

  if (signal.aborted) {
    // console.log('bam aborted!')
    throw AbortError('aborted');
  }
}

/// Skips to the next tick, then runs `checkAbortSignal`.
/// Await this to inside an otherwise synchronous loop to
/// provide a place to break when an abort signal is received.
/// @param {AbortSignal} signal
void abortBreakPoint(AbortSignal signal) {
  checkAbortSignal(signal);
}

bool canMergeBlocks(Chunk chunk1, Chunk chunk2) {
  return (chunk2.minv.blockPosition - chunk1.maxv.blockPosition < 65000 && //
      chunk2.maxv.blockPosition - chunk1.minv.blockPosition < 5000000);
}
